/*
 * @(#)XfvhdlConstantsFile.java        3.0                    2004/09/14
 *
 * This file is part of Xfuzzy 3.0, a design environment for fuzzy logic
 * based systems.
 *
 * (c) 2000 IMSE-CNM. The authors may be contacted by the email address:
 *                    xfuzzy-team@imse.cnm.es
 *
 * Xfuzzy is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * Xfuzzy is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

package xfuzzy.xfvhdl;

import xfuzzy.lang.*;

/**
* Clase que genera el fichero de constantes Constants.vhdl.
* @author Jos� Mar�a �vila Maireles, <b>e-mail</b>: josavimai@alum.us.es
* @version 3.0
*/
public class XfvhdlConstantsFile {

   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
   //			  M�TO_DOS P�BLICOS DE LA CLASE				        
   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

   /**
   * M�todo que calcula las variables que formar�n el fichero de 
   * constantes a partir de la especificaci�n del sistema.
   * @param spec Especificaci�n del sistema.
   * @param defuzzification M�todo de defuzzificaci�n que se utiliza.
   */
   public void calculateConstants(
      Specification spec,
      XfvhdlIDefuzzification defuzzification) {

      int temp[] = new int[3];

      // Averiguo el n�mero de entradas q tiene el sistema.
      XfvhdlProperties.entradas =
         spec.getSystemModule().getInputs().length;

      // Averiguo el n�mero de funciones miembro de la primera entrada 
      // (todas deben tener el mismo n�mero).
      XfvhdlProperties.n_fp =
         spec
            .getSystemModule()
            .getInputs()[0]
            .getType()
            .getAllMembershipFunctions()
            .length;
      for (int cont = 0; cont < XfvhdlProperties.entradas; cont++) {
         if (spec
            .getSystemModule()
            .getInputs()[cont]
            .getType()
            .getAllMembershipFunctions()
            .length
            != XfvhdlProperties.n_fp) {
            new XfvhdlError(3);
         }
      }

      // Averiguo el n�mero de bits que se necesitan para codificar 
      // las etiquetas.
      XfvhdlProperties.bits_etiq =
         (int) Math.ceil(
            Math.log((double) XfvhdlProperties.n_fp)
               / Math.log((double) 2));

      // Averiguo el n�mero de bits del bus de direcciones de la 
      // memoria de reglas.
      XfvhdlProperties.dir_regl =
         XfvhdlProperties.entradas * XfvhdlProperties.bits_etiq;

      // Averiguo el n�mero de filas de la memoria de reglas.
      XfvhdlProperties.reglas =
         (int) Math.pow((double) 2, (double) XfvhdlProperties.dir_regl);

      // Averiguo el n�mero de bits para el bus de direcciones de la 
      // memoria de antecedentes, el n�mero de filas de la memoria de 
      // antecedentes, la anchura de la memoria de antecedentes y
      // el n�mero de ciclos de pipeline.
      if (XfvhdlProperties.calcArithmetic == false) {
         XfvhdlProperties.dir_ant = XfvhdlProperties.N;
         XfvhdlProperties.fil =
            (int) Math.pow((double) 2, (double) XfvhdlProperties.N);
         XfvhdlProperties.M =
            (2 * XfvhdlProperties.grad) + XfvhdlProperties.bits_etiq;
         XfvhdlProperties.j_pipe =
            Math.max(
               (int) Math.pow(
                  (double) 2,
                  (double) XfvhdlProperties.entradas),
               XfvhdlProperties.N)
               + 1;
      } else {
         XfvhdlProperties.dir_ant = XfvhdlProperties.bits_etiq;
         XfvhdlProperties.fil =
            (int) Math.pow(
               (double) 2,
               (double) XfvhdlProperties.bits_etiq);
         XfvhdlProperties.M =
            XfvhdlProperties.entradas
               * (XfvhdlProperties.N + XfvhdlProperties.P);
         XfvhdlProperties.j_pipe =
            Math.max(
               (int) Math.pow(
                  (double) 2,
                  (double) XfvhdlProperties.entradas),
               Math.max(XfvhdlProperties.N, XfvhdlProperties.n_fp))
               + 1;
      }

      // Averiguo la anchura de la memoria de reglas, i_1 e i_2 
      // dependiendo del m�todo de defuzzificaci�n.	
      temp =
         defuzzification.calculateConstants(
            XfvhdlProperties.N,
            XfvhdlProperties.grad,
            XfvhdlProperties.K);
      XfvhdlProperties.w_reglas = temp[0];
      XfvhdlProperties.i_1 = temp[1];
      XfvhdlProperties.i_2 = temp[2];

      //	Averiguo el n�mero de bits necesarios para codificar j_pipe.
      XfvhdlProperties.w_pipe =
         (int) Math.ceil(
            Math.log((double) XfvhdlProperties.j_pipe)
               / Math.log((double) 2));

      // Averiguo los ciclos de carga de la memoria de antecedentes.
      XfvhdlProperties.i1 =
         (int) Math.ceil((double) XfvhdlProperties.M / 8);

      //	Averiguo los ciclos de carga de la memoria de reglas.
      XfvhdlProperties.i2 =
         (int) Math.ceil((double) XfvhdlProperties.w_reglas / 8);

      //	Averiguo el m�ximo n�mero de ciclos de carga.
      XfvhdlProperties.max_ciclos =
         Math.max(XfvhdlProperties.i1, XfvhdlProperties.i2);

      // Averiguo el m�ximo DB de memoria de antecedentes y reglas.
      XfvhdlProperties.w_bus =
         Math.max(XfvhdlProperties.M, XfvhdlProperties.w_reglas);

      //	Averiguo el m�ximo AB de memoria de antecedentes y reglas.
      XfvhdlProperties.w_dir =
         Math.max(XfvhdlProperties.dir_ant, XfvhdlProperties.dir_regl);

      // Averiguo el n�mero de bits del numerador del acumulador.
      XfvhdlProperties.D = XfvhdlProperties.i_2 + XfvhdlProperties.N + 3;

      //	Averiguo el n�mero de bits del denominador del acumulador.
      XfvhdlProperties.DR = XfvhdlProperties.i_2 + 3;
   }

   /**
   * M�todo que crea la cadena que ser� escrita en fichero 
   * Constants.vhdl.
   * @return Devuelve la cadena que ser� escrita en fichero 
   * Constants.vhdl.
   */
   public String createConstantsSource() {

      XfvhdlHeadFile head =
         new XfvhdlHeadFile(
            ".",
            XfvhdlProperties.outputFile + "Constants.vhdl",
            XfvhdlProperties.ficheroXFL);

      String code = head.getHead();

      code
         += "\n--***********************************************************************--\n"
         + "--                                                                       --\n"
         + "--   DESCRIPTION: This file contains the constants definitions used for  --\n"
         + "--                the fuzzy controller description.                      --\n"
         + "--                                                                       --\n"
         + "---------------------------------------------------------------------------\n"
         + "--                                                                       --\n"
         + "--   AUTHOR:      Jose Maria Avila Maireles                              --\n"
         + "--                                                                       --\n"
         + "--   VERSION:     Xfvhdl  ver0.1                          October 2003   --\n"
         + "--                                                                       --\n"
         + "--***********************************************************************--\n"
         + "\n"
         + "\n"
         + "\n"
         + "library IEEE;\n"
         + "use IEEE.std_logic_1164.all;\n"
         + "use IEEE.std_logic_arith.all;\n"
         + "\n"
         + "\n"
         + "package Constants is \n"
         + "\n"
         + "---------------------------------------------------------------------------\n"
         + "--                       Main constants definitions                      --\n"
         + "---------------------------------------------------------------------------\n"
         + "\n"
         + "\tconstant entradas\t\t: integer :="
         + XfvhdlProperties.entradas
         + ";\t\t-- Inputs to the fuzzy system\n"
         + "\tconstant N\t\t\t: integer :="
         + XfvhdlProperties.N
         + ";\t\t-- Bitsize of input\n"
         + "\tconstant grad\t\t: integer :="
         + XfvhdlProperties.grad
         + ";\t\t-- Bitsize of membership degree\n"
         + "\tconstant K\t\t\t: integer :="
         + XfvhdlProperties.K
         + ";\t\t-- Bitsize of defuzz. parameter\n"
         + "\tconstant n_fp\t\t: integer :="
         + XfvhdlProperties.n_fp
         + ";\t\t-- Number of membership functions\n"
         + "\tconstant P\t\t\t: integer :="
         + XfvhdlProperties.P
         + ";\t\t-- Bitsize of MF slope\n"
         + "\n"
         + "\n"
         + "---------------------------------------------------------------------------\n"
         + "--                   Secondary constants definitions                     --\n"
         + "---------------------------------------------------------------------------\n"
         + "\n"
         + "\tconstant bits_etiq\t: integer :="
         + XfvhdlProperties.bits_etiq
         + ";\t\t-- Bitsze of label\n"
         + "\tconstant dir_ant\t\t: integer :="
         + XfvhdlProperties.dir_ant
         + ";\t\t-- Bitsize of ant. memory A.B.\n"
         + "\tconstant fil\t\t: integer :="
         + XfvhdlProperties.fil
         + ";\t\t-- Rows for antecedents memory\n"
         + "\tconstant M\t\t\t: integer :="
         + XfvhdlProperties.M
         + ";\t\t-- Columns for antecedents memory\n"
         + "\tconstant dir_regl\t\t: integer :="
         + XfvhdlProperties.dir_regl
         + ";\t\t-- Bitsize of rules memory A.B.\n"
         + "\tconstant reglas\t\t: integer :="
         + XfvhdlProperties.reglas
         + ";\t\t-- Rows for rules memory\n"
         + "\tconstant w_reglas\t\t: integer :="
         + XfvhdlProperties.w_reglas
         + ";\t\t-- Colums for rules memory\n"
         + "\tconstant j_pipe\t\t: integer :="
         + XfvhdlProperties.j_pipe
         + ";\t\t-- Pipeline cycles\n"
         + "\tconstant w_pipe\t\t: integer :="
         + XfvhdlProperties.w_pipe
         + ";\t\t-- Bitsize of j_pipe\n"
         + "\tconstant i1\t\t\t: integer :="
         + XfvhdlProperties.i1
         + ";\t\t-- Cycles for ant. memory load\n"
         + "\tconstant i2\t\t\t: integer :="
         + XfvhdlProperties.i2
         + ";\t\t-- Cycles for rules memory load\n"
         + "\tconstant max_ciclos\t: integer :="
         + XfvhdlProperties.max_ciclos
         + ";\t\t-- Maximum of i1 and i2\n"
         + "\tconstant w_bus\t\t: integer :="
         + XfvhdlProperties.w_bus
         + ";\t\t-- Max. DB of ant. mem. and rules\n"
         + "\tconstant w_dir\t\t: integer :="
         + XfvhdlProperties.w_dir
         + ";\t\t-- Max. AB of ant. mem. and rules\n"
         + "\tconstant i_1\t\t: integer :="
         + XfvhdlProperties.i_1
         + ";\t\t-- Max. of N, K and grad\n"
         + "\tconstant i_2\t\t: integer :="
         + XfvhdlProperties.i_2
         + ";\t\t-- Max. of grad+K and grad*2\n"
         + "\tconstant D\t\t\t: integer :="
         + XfvhdlProperties.D
         + ";\t\t-- Bitsize of accumulator numerator\n"
         + "\tconstant DR\t\t\t: integer :="
         + XfvhdlProperties.DR
         + ";\t\t-- Bitsize of accumulator denominat.\n"
         + "\n"
         + "\n"
         + "---------------------------------------------------------------------------\n"
         + "--                        Functions definitions                          --\n"
         + "---------------------------------------------------------------------------\n"
         + "\n"
         + "\tfunction \"not\" (arg1: unsigned) return unsigned;\n"
         + "\tfunction \"not\" (arg1: signed) return signed;\n"
         + "\tfunction max (L, R: integer) return integer;\n"
         + "\tfunction min (L, R: integer) return integer;\n"
         + "\n"
         + "end Constants;\n"
         + "\n"
         + "\n"
         + "\n"
         + "---------------------------------------------------------------------------\n"
         + "--                        Package body definition                        --\n"
         + "---------------------------------------------------------------------------\n"
         + "\n"
         + "package body Constants is\n"
         + "\n"
         + "\tfunction \"not\" (arg1: unsigned) return unsigned is\n"
         + "\t\tbegin\n"
         + "\t\t\treturn(unsigned(not(std_logic_vector(arg1))));\n"
         + "\t\tend \"not\";\n"
         + "\n"
         + "\tfunction \"not\" (arg1: signed) return signed is\n"
         + "\t\tbegin\n"
         + "\t\t\treturn(signed(not(std_logic_vector(arg1))));\n"
         + "\t\tend \"not\";\n"
         + "\n"
         + "\tfunction max (L, R: integer) return integer is\n"
         + "\t\tbegin\n"
         + "\t\t\tif L > R then\n"
         + "\t\t\t\treturn L;\n"
         + "\t\t\telse\n"
         + "\t\t\t\treturn R;\n"
         + "\t\t\tend if;\n"
         + "\t\tend;\n"
         + "\n"
         + "\tfunction min (L, R: integer) return integer is\n"
         + "\t\tbegin\n"
         + "\t\t\tif L < R then\n"
         + "\t\t\t\treturn L;\n"
         + "\t\t\telse\n"
         + "\t\t\t\treturn R;\n"
         + "\t\t\tend if;\n"
         + "\t\tend;\n"
         + "\n"
         + "end Constants;";

      return code;
   }

} // Fin de la clase
